/**
 * MESH
 * ModulE Scripting Helper
 *
 * This is the base init script for Mesh. It is a multi purpose framework with extendable
 * capabilities. The goal is to have basic functionality of this Application stdLib 
 * dependancy free. Any extra features might be included as modules.
 *
 * IMPORTANT!!!
 *   All modules included in this script are required to be selfcontained or only core dependant 
 *   eg: if a module requires any function which would normaly be in stdLib directory
 *       it needs to include it on its own within the module hirarchy and therefor not
 *       interfer with the user's stdLib directories
 *       This only applies if you're planning to resdistribute the script.
 *
 *   Due to its dynamic modular nature the script is required to run uncompiled
 *   This Script requires AHK 1.0.48 or later to run as intended
 *
 *   Version 0.5 written Jan 2010 by derRaphael
 *   Released under EUPL 1.1 or later
 *
 * see the included ReadMe.txt for further information
 */

#SingleInstance

MeshVersionMajor := "0"
MeshVersionMinor := "5"
MeshVersionBuild := "2010-03-05" ; YYYY-MM-DD

If ( A_IsCompiled )
{
	MsgBox, 16, Information:, This Script requires to be run uncompiled.
	ExitApp
}

; Include any available Modules

; Check if modules and core subdirectories exists
If ( ( mEDir := InStr( FileExist( A_ScriptDir "\modules.enabled" ), "D" ) )
  && ( mADir := InStr( FileExist( A_ScriptDir "\modules.available" ), "D" ) )
  && (  bDir := InStr( FileExist( A_ScriptDir "\mesh.core" ), "D" ) ) )
{
	; Check for init script for module inclusion
	If ( FileExist( A_ScriptDir "\mesh.core\mesh.init.ahk" ) )
	{
		; Remove the file for proper rebuild
		FileDelete, % A_ScriptDir "\mesh.core\mesh.init.ahk"
	}

	; Rebuild the include file
	
	; Loop modules directory
	Loop, %A_ScriptDir%\modules.enabled\*.ahk, 0, 0
	{
		; Build an AutoExecuteLabel based on the FileName
		AutoExecuteLabel := RegExReplace( A_LoopFileName, "\.ahk|\W" )
		
		If ( FileExist( A_ScriptDir "\modules.available\" A_LoopFileName ) )
		{
			; Read the Module into Memory
			FileRead, ModuleToTest, % A_ScriptDir "\modules.available\" A_LoopFileName 
			
			; If the module's AutoExecuteLabel exists, add it to the execution list
			If ( InStr( ModuleToTest, AutoExecuteLabel "AutoExecute:" ) )
			{
				ItemPriority := "Auto"
				If ( FileExist( A_ScriptDir "\modules.enabled\" AutoExecuteLabel ".prio" ) )
				{
					PrioFileData := ""
					FileRead, PrioFileData, % A_ScriptDir "\modules.enabled\" AutoExecuteLabel ".prio"
					If ( ! RegExMatch( PrioFileData, "(?P<Priority>^[-\d]+)", Item ) )
					{
						ItemPriority := "Auto"
					}
				}
				mConst_PriorityStack( "AutoExecutes", AutoExecuteLabel, ItemPriority )
			}
		}
	}
	
	; Init Variables used for AutoExecute and include stuff
	IncludeModuleList := AutoExecuteModuleList := ""
	
	; mCore_sortStack returns the stores Values sorted numerically reverse
	; by means: a higher priority is listed earlier
	Collection := mCore_sortStack( "AutoExecutes" )
	
	; Build Gosub Executions and Includes according to AutoExecute-Stack
	Loop, Parse, Collection, `n, `r
	{
		AutoExecuteLabel := RegExReplace( A_LoopField, "(^\d+|\W)" )
	
		; Build the AutoExecute Section (init) for the modules
		AutoExecuteModuleList .= NewLine( AutoExecuteModuleList )
						   . "`t; Module " AutoExecuteLabel ".ahk"
						   . "`n`tGosub, " AutoExecuteLabel "AutoExecute"
		; Build the include section for the modules
		IncludeModuleList .= NewLine( IncludeModuleList ) 
						   . "#Include modules.available\" AutoExecuteLabel ".ahk"

		; Do we have a custom ModuleDirectory (eg a larger Projekt)
		If ( InStr( FileExist( A_ScriptDir "\modules.available\" AutoExecuteLabel ) , "D" ) )
		{
			; Dive into SubDirectories if they exists and include any found ahk scripts
			Loop,% A_ScriptDir "\modules.available\" AutoExecuteLabel "\*.*", 1, 1
			{
				If ( A_LoopFileExt = "ahk" )
				{
					IncludeModuleList .= NewLine( IncludeModuleList ) 
									   . "#Include " SubStr( A_LoopFileFullPath, StrLen( A_ScriptDir )+2 )
				}
			}
		}
	}
	
	; Write the new mesh.init.ahk-script
	FileAppend,
	(Ltrim Join`n
	; MESH AutoIncluder Init Script Version 0.1
	; Mesh - ModulE Scripting Helper
	;
	; This file is part of MESH Version %MeshVersionMajor%.%MeshVersionMinor%.%MeshVersionBuild%
	; Template was autogenerated by %A_ScriptName%
	;
	; !!! DO NOT EDIT THIS FILE, SINCE IT WILL BE DELETED ON EACH RUN !!!
	;
	Gosub, AutoExecute
	Return
	
	AutoExecute:
	`t;Basic Initialization
	`t#SingleInstance
	`t#NoEnv
	`tSetWorkingDir, `%A_ScriptDir`%
	`tOnExit, MeshOnExit
	
	`t; Set Version Info for modules
	`tMeshVersionMajor := "%MeshVersionMajor%"
	`tMeshVersionMinor := "%MeshVersionMinor%"
	`tMeshVersionBuild := "%MeshVersionBuild%"
	
	`t; Initialize all modules
	%AutoExecuteModuleList%
	
	`tmHelper_OverrideOrPreExec()

	`t; Initialize GUI for mesh
	`tGosub, MeshGuiDefaultInit
	
	`tmHelper_PostExec()
	Return
	
	MeshOnExit:
	`tmHelper_OverrideOrPreExec()
	
	`tAvailModules := mCore_get("AvailModules")
	`tLoop,Parse,AvailModules,``n
	`t{
	`t`tIf ( IsLabel( A_LoopField "OnExit" ) )
	`t`t{
	`t`t`tGosub, `% A_LoopField "OnExit"
	`t`t}
	`t}
	
	`tmHelper_PostExec()
	
	`tExitApp
	Return
	
	; Include the mesh.core files
	#Include %A_ScriptDir%
	
	; GUI Builder and its subroutines
	#Include mesh.core\mesh.gui.ahk
	; Hotkeys
	#Include mesh.core\mesh.hotkeys.ahk
	; Communication
	#Include mesh.core\mesh.communication.ahk
	; Memory Core Ops
	#Include mesh.core\mesh.mCore.ahk
	; Generic Constructors
	#Include mesh.core\mesh.constructors.ahk
	; Generic Helper
	#Include mesh.core\mesh.helper.ahk
	
	; The modules to include into Mesh
	%IncludeModuleList%
	), % A_ScriptDir "\mesh.core\mesh.init.ahk"
	
	; Start the app including its new Modules
	Run, "%A_AhkPath%" /ErrorStdOut "%A_ScriptDir%\mesh.core\mesh.init.ahk", % A_ScriptDir "\base.mesh"
	ExitApp
}
Else
{
	Err := bDir ? "" : "Base directory"
	Err := mEDir ? Err : ( Err != "" ? Err " and " : "" ) "enabled Modules directory"
	Err := mADir ? Err : ( Err != "" ? Err " and " : "" ) "available Modules directory"
	MsgBox, 16, Error, % "No " Err " found. Check if the application is installed correctly."
	ExitApp
}

NewLine( Data )
{
	Return ( StrLen( Data ) ? "`n" : "" )
}

#Include mesh.core\mesh.mCore.ahk
#Include mesh.core\mesh.constructors.ahk